package services

import (
	"b2c-delivery-optimization/internal/model"
	"b2c-delivery-optimization/internal/utils"
	"fmt"
	"time"

	"gorm.io/gorm"
)

// PickingService 分拣任务服务
type PickingService struct {
	db *gorm.DB
}

// NewPickingService 创建分拣任务服务实例
func NewPickingService() *PickingService {
	return &PickingService{
		db: utils.DB,
	}
}

// CreatePickingTask 创建分拣任务
func (s *PickingService) CreatePickingTask(order *model.Order) (*model.PickingTask, error) {
	// 开启事务
	tx := s.db.Begin()
	if tx.Error != nil {
		return nil, fmt.Errorf("开启事务失败: %v", tx.Error)
	}

	// 创建分拣任务
	task := &model.PickingTask{
		ID:             fmt.Sprintf("PT%s", time.Now().Format("20060102150405")),
		OrderID:        order.ID,
		WaveID:         order.WaveID, // 直接使用指针
		Status:         model.PickingStatusPending,
		Location:       order.Location,
		Priority:       order.Priority,
		CreateTime:     time.Now(),
		LastUpdateTime: time.Now(),
	}

	// 创建分拣任务
	if err := tx.Create(task).Error; err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("创建分拣任务失败: %v", err)
	}

	// 创建分拣项
	for _, item := range order.Items {
		pickingItem := &model.PickingItem{
			TaskID:     task.ID,
			ProductID:  item.ProductID,
			SKU:        item.SKU,
			Quantity:   item.Quantity,
			PickedQty:  0,
			PackedQty:  0,
			Status:     model.PickingItemStatusPending,
			CreateTime: time.Now(),
			UpdateTime: time.Now(),
		}
		if err := tx.Create(pickingItem).Error; err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("创建分拣项失败: %v", err)
		}
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return nil, fmt.Errorf("提交事务失败: %v", err)
	}

	return task, nil
}

// GetPickingTask 获取分拣任务
func (s *PickingService) GetPickingTask(id string) (*model.PickingTask, error) {
	var task model.PickingTask
	if err := s.db.Preload("Items").First(&task, "id = ?", id).Error; err != nil {
		return nil, fmt.Errorf("获取分拣任务失败: %v", err)
	}
	return &task, nil
}

// ListPickingTasks 获取分拣任务列表
func (s *PickingService) ListPickingTasks(page, pageSize int) ([]model.PickingTask, int64, error) {
	var tasks []model.PickingTask
	var total int64

	// 获取总数
	if err := s.db.Model(&model.PickingTask{}).Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取分拣任务总数失败: %v", err)
	}

	// 获取分页数据
	offset := (page - 1) * pageSize
	if err := s.db.Preload("Items").
		Order("create_time DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&tasks).Error; err != nil {
		return nil, 0, fmt.Errorf("获取分拣任务列表失败: %v", err)
	}

	return tasks, total, nil
}

// UpdatePickingTaskStatus 更新分拣任务状态
func (s *PickingService) UpdatePickingTaskStatus(id string, status model.PickingStatus) error {
	updates := map[string]interface{}{
		"status":           status,
		"last_update_time": time.Now(),
	}

	if status == model.PickingStatusInProgress {
		updates["start_time"] = time.Now()
	} else if status == model.PickingStatusCompleted {
		updates["end_time"] = time.Now()
	}

	if err := s.db.Model(&model.PickingTask{}).
		Where("id = ?", id).
		Updates(updates).Error; err != nil {
		return fmt.Errorf("更新分拣任务状态失败: %v", err)
	}
	return nil
}

// UpdatePickingItemStatus 更新分拣项状态
func (s *PickingService) UpdatePickingItemStatus(id uint, status model.PickingItemStatus, pickedQty, packedQty int) error {
	updates := map[string]interface{}{
		"status":      status,
		"picked_qty":  pickedQty,
		"packed_qty":  packedQty,
		"update_time": time.Now(),
	}

	if err := s.db.Model(&model.PickingItem{}).
		Where("id = ?", id).
		Updates(updates).Error; err != nil {
		return fmt.Errorf("更新分拣项状态失败: %v", err)
	}

	// 检查是否需要更新任务状态
	var task model.PickingTask
	if err := s.db.First(&task, "id = (SELECT task_id FROM picking_items WHERE id = ?)", id).Error; err != nil {
		return fmt.Errorf("获取分拣任务失败: %v", err)
	}

	// 检查所有分拣项的状态
	var items []model.PickingItem
	if err := s.db.Where("task_id = ?", task.ID).Find(&items).Error; err != nil {
		return fmt.Errorf("获取分拣项列表失败: %v", err)
	}

	allCompleted := true
	for _, item := range items {
		if item.Status != model.PickingItemStatusCompleted {
			allCompleted = false
			break
		}
	}

	if allCompleted {
		if err := s.UpdatePickingTaskStatus(task.ID, model.PickingStatusCompleted); err != nil {
			return err
		}
	}

	return nil
}

// AssignPickingTask 分配分拣任务
func (s *PickingService) AssignPickingTask(id string, assignedTo string) error {
	if err := s.db.Model(&model.PickingTask{}).
		Where("id = ?", id).
		Updates(map[string]interface{}{
			"assigned_to":      assignedTo,
			"status":           model.PickingStatusInProgress,
			"start_time":       time.Now(),
			"last_update_time": time.Now(),
		}).Error; err != nil {
		return fmt.Errorf("分配分拣任务失败: %v", err)
	}
	return nil
}

// GetPickingTasksByStatus 根据状态获取分拣任务列表
func (s *PickingService) GetPickingTasksByStatus(status model.PickingStatus) ([]model.PickingTask, error) {
	var tasks []model.PickingTask
	if err := s.db.Preload("Items").
		Where("status = ?", status).
		Order("create_time DESC").
		Find(&tasks).Error; err != nil {
		return nil, fmt.Errorf("获取分拣任务列表失败: %v", err)
	}
	return tasks, nil
}

// GetPickingTasksByPriority 根据优先级获取分拣任务列表
func (s *PickingService) GetPickingTasksByPriority(priority int) ([]model.PickingTask, error) {
	var tasks []model.PickingTask
	if err := s.db.Preload("Items").
		Where("priority = ?", priority).
		Order("create_time DESC").
		Find(&tasks).Error; err != nil {
		return nil, fmt.Errorf("获取分拣任务列表失败: %v", err)
	}
	return tasks, nil
}
